﻿using Common.AspNetCore;
using FCP.Data.Entity;
using Common.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using FCP.Api.Models;
using Common.RunModels.FCP;
using FCP.Api.Utils;
using Common.Infrastructure.Structs;
using Common.Models.FCP;
using Microsoft.Extensions.Configuration;
using FCP.Api.Repository;
using System.Security.Cryptography;
using Common.Infrastructure.Utils;
using Common.RunModels.Base;
using static System.Net.Mime.MediaTypeNames;
using Common.Models.Base;

namespace FCP.Api.Service
{
    public class FCPService : CommonService
    {
        private readonly IConfiguration config;
        private readonly string lang;
        private readonly FCPRepository fcpRepository;
        public FCPService(IServiceProvider provider, IConfiguration c, FCPRepository fcp) : base(provider)
        {
            this.config = c;
            this.fcpRepository = fcp;

            this.lang = !string.IsNullOrEmpty(this.config["DefaultLang"]) ? this.config["DefaultLang"] : "CN";
        }

        public async Task FormConfigVersionAsync(string fcpFormId)
        {
            if (string.IsNullOrEmpty(fcpFormId)) return;
            var form = await this.fcpRepository.CommonRepository.GetEntityAsync<t_form>(fcpFormId);
            await FormConfigVersionAsync(form.org_id, new List<string>() { fcpFormId });
        }

        public async Task FormConfigVersionByFormCodesAsync(FCPFormVersionResetParam param)
        {
            if (param.FormCodes == null || !param.FormCodes.Any()) return;
            var codes = param.FormCodes;
            var forms = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_form>(null, t => codes.Contains(t.code));

            var group = forms.GroupBy(t => t.org_id).ToList();

            List<t_form_version> addFormVersions = new List<t_form_version>();
            foreach (var g in group)
            {
                if (param.OrgIds != null && param.OrgIds.Any() && !param.OrgIds.Any(t => t == g.Key))
                {
                    continue;
                }

                List<string> cookies = new List<string>();
                await GetCookieKey(g.Select(t => t.id).ToList(), cookies);

                foreach (var item in cookies)
                {
                    t_form_version d = new t_form_version();
                    d.org_id = g.Key;
                    d.create_time = DateTime.Now;
                    this.SetEntityId(d);
                    d.remove_cookie_key = item;
                    addFormVersions.Add(d);
                }
            }

            await this.fcpRepository.CommitChangesByCommonAsync(() =>
            {
                this.fcpRepository.CommonRepository.AddEntities(addFormVersions);
            });
        }

        public async Task FormConfigVersionAsync(string orgId, List<string> formIds)
        { 
            List<string> cookies = new List<string>(); 
            await GetCookieKey(formIds, cookies);

            List<t_form_version> addFormVersions = new List<t_form_version>();

            foreach (var item in cookies)
            {
                t_form_version d = new t_form_version();
                d.org_id = orgId;
                d.create_time = DateTime.Now;
                this.SetEntityId(d);
                d.remove_cookie_key = item;
                addFormVersions.Add(d);
            }

            await this.fcpRepository.CommitChangesByCommonAsync(() =>
            {
                this.fcpRepository.CommonRepository.AddEntities(addFormVersions);
            }); 
        }


        public async Task<List<string>> GetFormConfigSqlAsync(FCPSqlRequest model)
        {
            return await DoGetFormConfigSqlAsync(model);
        }

        public async Task<List<EnumInfo>> GetEnumInfosAsync(ApiParam apiParam)
        {
            var lang = apiParam.Lang;
            var isGetDisableEnum = LibSysUtils.ToBoolean(apiParam.Params.FirstOrDefault(t => t.Key == "is_get_disable_enum")?.Value);
            var enums = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_enum>(t => t.org_id == apiParam.OrgId && t.type == 0);
            var enumIds = enums.Select(t => t.id).ToList();
            var enumDetails = enumIds.Any() ? await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_enum_detail>(t => enumIds.Contains(t.enum_id)) : new List<t_enum_detail>();
            var labelIds = enumDetails != null ? enumDetails.Where(t => !string.IsNullOrEmpty(t.label_label_id)).Select(t => t.label_label_id).ToList() : new List<string>();
            var labelDetails = labelIds.Any() ? await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_label_detail>(null, t => labelIds.Contains(t.label_id)) : null;

            List<EnumInfo> ret = new List<EnumInfo>();
            enums?.ForEach(t =>
            {
                EnumInfo info = new EnumInfo() { EnumName = t.enum_name };
                enumDetails.Where(t1 => t1.enum_id == t.id).OrderBy(t => t.sort_index).ThenBy(t => t.value).ForEach(t1 =>
                    {
                        if (!isGetDisableEnum && t1.enable_status == 1)
                        {
                            return;
                        }

                        var lb = labelDetails?.FirstOrDefault(t6 => t6.label_id == t1.label_label_id && t6.lang == lang);
                        if (lb == null)
                        {
                            lb = labelDetails?.Where(t6 => t6.label_id == t1.label_label_id).OrderBy(t6 => t6.lang).FirstOrDefault();
                        }

                        info.Options.Add(new EnumDetailInfo()
                        {
                            Label = lb?.label ?? t1.label,
                            SortIndex = t1.sort_index,
                            Value = LibSysUtils.ToInt(t1.value)
                        });
                    });
                ret.Add(info);
            });

            return ret;
        }


        public async Task<List<EnumByStringInfo>> GetEnumByStringInfosByEnumNameAsync(ApiParam apiParam)
        {
            var lang = apiParam.Lang;
            var isGetDisableEnum = LibSysUtils.ToBoolean(apiParam.Params.FirstOrDefault(t => t.Key == "is_get_disable_enum")?.Value);
            var keys = apiParam.Keyword.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            var enums = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_enum>(t => t.org_id == apiParam.OrgId && t.type == 1 && keys.Contains(t.enum_name));
            var enumIds = enums.Select(t => t.id).ToList();
            var enumDetails = enumIds.Any() ? await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_enum_detail>(t => enumIds.Contains(t.enum_id)) : new List<t_enum_detail>();
            var labelIds = enumDetails != null ? enumDetails.Where(t => !string.IsNullOrEmpty(t.label_label_id)).Select(t => t.label_label_id).ToList() : new List<string>();
            var labelDetails = labelIds.Any() ? await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_label_detail>(null, t => labelIds.Contains(t.label_id)) : null;

            List<EnumByStringInfo> ret = new List<EnumByStringInfo>();
            enums?.ForEach(t =>
            {
                EnumByStringInfo info = new EnumByStringInfo() { EnumName = t.enum_name };
                enumDetails.Where(t1 => t1.enum_id == t.id).OrderBy(t => t.sort_index).ThenBy(t => t.value).ForEach(t1 =>
                {
                    if (!isGetDisableEnum && t1.enable_status == 1)
                    {
                        return;
                    }

                    var lb = labelDetails?.FirstOrDefault(t6 => t6.label_id == t1.label_label_id && t6.lang == lang);
                    if (lb == null)
                    {
                        lb = labelDetails?.Where(t6 => t6.label_id == t1.label_label_id).OrderBy(t6 => t6.lang).FirstOrDefault();
                    }

                    info.Options.Add(new EnumByStringDetailInfo()
                    {
                        Label = lb?.label ?? t1.label,
                        SortIndex = t1.sort_index,
                        Value = t1.value
                    });
                });
                ret.Add(info);
            });

            return ret;
        }


        public async Task<List<m_label>> GetBaseLabelsByIdsAsync(ModelIdRequest model)
        {
            var result = await this.fcpRepository.CommonModelRepository.GetModelsAsync<m_label>(model.Ids);
            await FillLangDataByBaseLabelAsync(result);
            return result;
        }

        public async Task<bool> SaveBaseLabelAsync(ModelSaveRequest request)
        {
            List<t_label> addBaseLabels = new List<t_label>();
            List<t_label> updateBaseLabels = new List<t_label>();
            List<t_label_detail> addBaseLabelDetails = new List<t_label_detail>();
            List<t_label_detail> updateBaseLabelDetails = new List<t_label_detail>();
            List<t_form_version> addFormVersions = new List<t_form_version>();
            var processR = request.Details.FirstOrDefault(t => t.ModelName == "t_label" || t.ModelName == "m_label");

            if (processR == null || string.IsNullOrEmpty(processR.ModelData))
            {
                return true;
            }

            var list = processR.ModelData.ToObjectFromJson<List<m_label>>();

            list = await LangChangeAsync(list);
            var ids = list.Select(t => t.id).Distinct().ToList();

            var baseLabels = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_label>(ids);
            var baseLabelIds = baseLabels.Select(t => t.id).ToList();
            var baseLabelDetails = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_label_detail>(null, t => baseLabelIds.Contains(t.label_id));

            foreach (var s in list)
            {
                var b = baseLabels.FirstOrDefault(t => t.id == s.id);

                DoAddLabelDetail(b, baseLabelDetails, addBaseLabelDetails, updateBaseLabelDetails, s.label_label_cn, "CN");
                DoAddLabelDetail(b, baseLabelDetails, addBaseLabelDetails, updateBaseLabelDetails, s.label_label_en, "EN");
                DoAddLabelDetail(b, baseLabelDetails, addBaseLabelDetails, updateBaseLabelDetails, s.label_label_th, "TH");
                var pp = addFormVersions.FirstOrDefault(t => t.org_id == b?.org_id);
                if (pp == null)
                {
                    pp = new t_form_version() { org_id = b?.org_id, remove_cookie_key = "clear_all_form", create_time = DateTime.Now };
                    this.SetEntityId(pp);
                    addFormVersions.Add(pp);
                }
            }

            await this.fcpRepository.CommitChangesByCommonAsync(() =>
            {
                this.fcpRepository.CommonRepository.AddEntities(addBaseLabels);
                this.fcpRepository.CommonRepository.AddEntities(addBaseLabelDetails);
                this.fcpRepository.CommonRepository.UpdateEntities(updateBaseLabels);
                this.fcpRepository.CommonRepository.UpdateEntities(updateBaseLabelDetails);
                this.fcpRepository.CommonRepository.AddEntities(addFormVersions);
            });

            return !this.HasThrow;
        }

        public async Task<ApiPagedResult<m_label>> GetBaseLabelOrderPageAsync(ModelOrderPageRequest model)
        {
            var boxkey = model.OrderPageParam.Params.FirstOrDefault(t => t.Key == "detail_key")?.Value; 
            if (!string.IsNullOrEmpty(boxkey))
            {
                var details = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_label_detail>(null, t => t.org_id == model.OrderPageParam.OrgId && t.label.Contains(boxkey));
                if (!details.Any())
                {
                    return new ApiPagedResult<m_label>();
                }

                model.OrderPageParam.Group.Rules.Add(new ApiRuleParam() { Field = "id", Value = string.Join(",", details.Select(t => t.label_id).Distinct()), Operate = ApiRuleOperateEnum.InByString });
            }
             
            var result = await this.fcpRepository.CommonModelRepository.GetOrderPageModelsAsync<m_label>(model.OrderPageParam);
            if (result.Data.Any())
            {
                await FillLangDataByBaseLabelAsync(result.Data);
            }

            return result;
        }

        public async Task<bool> SaveEnumInfoToEnumAsync(FCPEnumInfoParamModel model)
        {
            var keys = model.Enums.Select(t=>t.EnumName).ToList();
            var enums = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_enum>(t => t.org_id == model.OrgId && t.type == 0 && keys.Contains(t.enum_name));
            var enumIds = enums.Select(t => t.id).ToList();
            var enumDetails = enumIds.Any() ? await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_enum_detail>(t => enumIds.Contains(t.enum_id)) : new List<t_enum_detail>();
            var labelIds = enumDetails != null ? enumDetails.Where(t => !string.IsNullOrEmpty(t.label_label_id)).Select(t => t.label_label_id).ToList() : new List<string>();
            var labelDetails = labelIds != null && labelIds.Any() ? await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_label_detail>(null, t => labelIds.Contains(t.label_id)) : null;

            List<t_label> addBaseLabels = new List<t_label>();
            List<t_label> updateBaseLabels = new List<t_label>();
            List<t_label_detail> addBaseLabelDetails = new List<t_label_detail>();
            List<t_label_detail> updateBaseLabelDetails = new List<t_label_detail>();

            List<t_enum> addEnums = new List<t_enum>();
            List<t_enum_detail> addEnumDetails = new List<t_enum_detail>();
            List<t_enum> updateEnums = new List<t_enum>();
            List<t_enum_detail> updateEnumDetails = new List<t_enum_detail>();
             
            foreach(var enumInfo in model.Enums)
            {
                var en = enums?.FirstOrDefault(t => t.enum_name == enumInfo.EnumName);
                if (en == null)
                {
                    en = new t_enum() { enum_name = enumInfo.EnumName, org_id = model.OrgId };
                    this.SetEntityId(en);
                    addEnums.Add(en);
                    enums.Add(en);
                }

                enumInfo.Options.ForEach(t =>
                {
                    var v = t.Value.ToString();
                    var pps = enumDetails?.FirstOrDefault(t1 => t1.enum_id == en.id && t1.value == v);
                    if (pps == null)
                    {
                        pps = new t_enum_detail() { enum_id = en.id, org_id = en.org_id, value = v };
                        this.SetEntityId(pps, pps.enum_id);
                        addEnumDetails.Add(pps);
                        enumDetails.Add(pps);
                    }
                    else
                    {
                        if (addEnumDetails.Any(t => t.id == pps.id))
                        {
                            return;
                        }

                        if (pps.label == t.Label && pps.sort_index == t.SortIndex)
                        {
                            return;
                        }

                        updateEnumDetails.Add(pps);
                    }

                    pps.label = t.Label;
                    pps.sort_index = t.SortIndex;


                    var p = labelDetails?.FirstOrDefault(t2 => t2.label_id == pps.label_label_id && t2.lang == lang);
                    if (p == null)
                    {
                        if (string.IsNullOrEmpty(pps.label_label_id))
                        {
                            var pt = new t_label() { org_id = pps.org_id };
                            this.SetEntityId(pt);
                            addBaseLabels.Add(pt);
                            pps.label_label_id = pt.id;
                        }

                        p = new t_label_detail() { org_id = pps.org_id, label_id = pps.label_label_id, lang = lang };
                        this.SetEntityId(p, p.label_id);
                        addBaseLabelDetails.Add(p);
                    }
                    else
                    {
                        if (!p.is_edit_by_menu || p.label != t.Label)
                        {
                            updateBaseLabelDetails.Add(p);
                        }
                    }

                    p.label = t.Label;
                });
               
            }


            await this.fcpRepository.CommitChangesByCommonAsync(() =>
            {
                this.fcpRepository.CommonRepository.AddEntities(addEnums);
                this.fcpRepository.CommonRepository.AddEntities(addEnumDetails);
                this.fcpRepository.CommonRepository.UpdateEntities(updateEnums);
                this.fcpRepository.CommonRepository.UpdateEntities(updateEnumDetails);

                this.fcpRepository.CommonRepository.AddEntities(addBaseLabels);
                this.fcpRepository.CommonRepository.AddEntities(addBaseLabelDetails);
                this.fcpRepository.CommonRepository.UpdateEntities(updateBaseLabels);
                this.fcpRepository.CommonRepository.UpdateEntities(updateBaseLabelDetails); 
            });

            return !this.HasThrow;
        }


        public async Task<bool> SaveEnumAsync(ModelSaveRequest request)
        {
            List<t_label> addBaseLabels = new List<t_label>();
            List<t_label> updateBaseLabels = new List<t_label>();
            List<t_label_detail> addBaseLabelDetails = new List<t_label_detail>();
            List<t_label_detail> updateBaseLabelDetails = new List<t_label_detail>();
             

            var processR = request.Details.FirstOrDefault(t => t.ModelName == "t_enum_detail" || t.ModelName == "m_enum_detail");
            var processR2 = request.Details.FirstOrDefault(t => t.ModelName == "t_enum" || t.ModelName == "m_enum");
            if (processR == null || string.IsNullOrEmpty(processR.ModelData))
            {
                return true;
            }



            var enumDetailList = processR.ModelData.ToObjectFromJson<List<t_enum_detail>>();
            var enumList = processR2.ModelData?.ToObjectFromJson<List<t_enum>>();
            var baseLabelIds = enumDetailList.Where(t=>!string.IsNullOrEmpty(t.label_label_id)) .Select(t => t.label_label_id).Distinct().ToList();
             
            var baseLabelDetails = baseLabelIds.Any() ? await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_label_detail>(null, t => baseLabelIds.Contains(t.label_id)) : null;

            foreach (var s in enumDetailList)
            {
                var p = baseLabelDetails?.FirstOrDefault(t2 => t2.label_id == s.label_label_id && t2.lang == lang);
                if (p == null)
                {
                    if (string.IsNullOrEmpty(s.label_label_id))
                    {
                        var pt = new t_label() { org_id = s.org_id };
                        this.SetEntityId(pt);
                        addBaseLabels.Add(pt);
                        s.label_label_id = pt.id;
                    }

                    p = new t_label_detail() { org_id = s.org_id, label_id = s.label_label_id, lang = lang };
                    this.SetEntityId(p, p.label_id);
                    addBaseLabelDetails.Add(p);
                }
                else
                {
                    if (!p.is_edit_by_menu || p.label != s.label)
                    {
                        updateBaseLabelDetails.Add(p);
                    }
                }

                p.label = s.label;
            }

            await this.fcpRepository.CommitChangesByCommonAsync(() =>
            {
                this.fcpRepository.CommonRepository.SaveEntities(enumList);
                this.fcpRepository.CommonRepository.SaveEntities(enumDetailList);
                this.fcpRepository.CommonRepository.AddEntities(addBaseLabels);
                this.fcpRepository.CommonRepository.AddEntities(addBaseLabelDetails);
                this.fcpRepository.CommonRepository.UpdateEntities(updateBaseLabels);
                this.fcpRepository.CommonRepository.UpdateEntities(updateBaseLabelDetails);
            });

            return !this.HasThrow;
        }

        private async Task<List<m_label>> LangChangeAsync(List<m_label> model)
        {
            var text = new TranslateRequest()
            {
                sysCode = "MES",
                srcLang = "zh",
                tgtLang = "en",
            };

            model.ForEach(o =>
            {
                text.text.Add(o.label_label_cn);
            });

            WebApiPostRequest request = new WebApiPostRequest
            {
                Url = this.config["Translate"],
                Obj = text
            };

            var response = await WebApiUtils.PostAsync(request);
            var translateReponse = response?.Data.ToObjectFromJson<TranslateReponse>();
            if (translateReponse == null)
            {
                return null;
            }

            var index = 0;
            foreach (var item in model)
            {
                if (string.IsNullOrEmpty(item.label_label_en))
                {
                    var tem = translateReponse.data.text[index];
                    if (item.label_label_cn != tem)
                    {
                        item.label_label_en = tem;
                    }
                }

                index++;
            }

            text.tgtLang = "th";
            request = new WebApiPostRequest
            {
                Url = this.config["Translate"],
                Obj = text
            };

            response = await WebApiUtils.PostAsync(request);
            translateReponse = response?.Data.ToObjectFromJson<TranslateReponse>();
            if (translateReponse == null)
            {
                return null;
            }

            index = 0;
            foreach (var item in model)
            {
                if (string.IsNullOrEmpty(item.label_label_th))
                {
                    var tem = translateReponse.data.text[index];
                    if (item.label_label_cn != tem)
                    {
                        item.label_label_th = tem;
                    }
                }

                index++;
            }

            return model;
        }

        private async Task<List<string>> DoGetFormConfigSqlAsync(FCPSqlRequest model)
        {
            List<string> rets = new List<string>();
            List<string> fcpFormIds = new List<string>();
            List<string> labelIds = new List<string>();

            if (string.IsNullOrEmpty(model.DestOrgId))
            {
                model.DestOrgId = model.OrgId;
            }
            #region 表单配置
            Expression<Func<t_form, bool>> expression = t => t.org_id == model.OrgId;
            if (!model.IsInitOrg && model.Time != null)
                expression = expression.And(t => t.modify_time > model.Time);
            if (!model.IsInitOrg && model.FormIds != null && model.FormIds.Any())
                expression = expression.And(t => model.FormIds.Contains(t.id));

            var forms = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_form>(expression);
            forms.ForEach(t =>
            {
                DoGetSqlByEntity(model.AccessType, t, rets, model.DestOrgId, model.SqlType);
            });

            await GetSqlByFcpTreeBaseAsync<t_table>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.label_label_id)) labelIds.Add(t.label_label_id);
            });
            await GetSqlByFcpBaseAsync<t_table_btn>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.btn_label_id)) labelIds.Add(t.btn_label_id);
            });
            await GetSqlByFcpBaseAsync<t_table_field>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.field_label_id)) labelIds.Add(t.field_label_id);
            });
            await GetSqlByFcpTreeBaseAsync<t_table_field_filter_group>(model, fcpFormIds, rets, null);
            await GetSqlByFcpBaseAsync<t_table_field_filter_field>(model, fcpFormIds, rets, null);
            await GetSqlByFcpTreeBaseAsync<t_table_filter_group>(model, fcpFormIds, rets, null);
            await GetSqlByFcpBaseAsync<t_table_filter_field>(model, fcpFormIds, rets, null);
            await GetSqlByFcpBaseAsync<t_table_panel>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.label_label_id)) labelIds.Add(t.label_label_id);
            });

            await GetSqlByFcpBaseAsync<t_tree>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.label_label_id)) labelIds.Add(t.label_label_id);
            });
            await GetSqlByFcpBaseAsync<t_tree_btn>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.btn_label_id)) labelIds.Add(t.btn_label_id);
            });
            await GetSqlByFcpBaseAsync<t_tree_field>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.field_label_id)) labelIds.Add(t.field_label_id);
            });
            await GetSqlByFcpBaseAsync<t_search>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.label_label_id)) labelIds.Add(t.label_label_id);
            });
            await GetSqlByFcpBaseAsync<t_search_field>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.field_label_id)) labelIds.Add(t.field_label_id);
            });
            await GetSqlByFcpBaseAsync<t_search_field_filter_field>(model, fcpFormIds, rets, null);
            await GetSqlByFcpTreeBaseAsync<t_search_field_filter_group>(model, fcpFormIds, rets, null);

            await GetSqlByFcpTreeBaseAsync<t_edit>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.label_label_id)) labelIds.Add(t.label_label_id);
            });
            await GetSqlByFcpBaseAsync<t_edit_btn>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.btn_label_id)) labelIds.Add(t.btn_label_id);
            });
            await GetSqlByFcpBaseAsync<t_edit_field>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.field_label_id)) labelIds.Add(t.field_label_id);
            });
            await GetSqlByFcpBaseAsync<t_edit_field_filter_field>(model, fcpFormIds, rets, null);
            await GetSqlByFcpTreeBaseAsync<t_edit_field_filter_group>(model, fcpFormIds, rets, null);
            await GetSqlByFcpBaseAsync<t_edit_field_map>(model, fcpFormIds, rets, null);
            await GetSqlByFcpBaseAsync<t_edit_field_map_detail>(model, fcpFormIds, rets, null);
            await GetSqlByFcpBaseAsync<t_edit_panel>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.label_label_id)) labelIds.Add(t.label_label_id);
            });


            await GetSqlByFcpBaseAsync<t_custom>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.label_label_id)) labelIds.Add(t.label_label_id);
            });
            await GetSqlByFcpBaseAsync<t_custom_btn>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.btn_label_id)) labelIds.Add(t.btn_label_id);
            });

            await GetSqlByFcpBaseAsync<t_chart>(model, fcpFormIds, rets, (t) =>
            {
                if (!string.IsNullOrEmpty(t.label_label_id)) labelIds.Add(t.label_label_id);
            });

            if (labelIds.Any())
            {
                var labels = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_label>(labelIds);
                labels.ForEach(t =>
                {
                    DoGetSqlByEntity(model.AccessType, t, rets, model.DestOrgId, model.SqlType);
                });
                var labelDetails = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_label_detail>(t => labelIds.Contains(t.label_id));
                labelDetails.ForEach(t =>
                {
                    DoGetSqlByEntity(model.AccessType, t, rets, model.DestOrgId, model.SqlType);
                });
            }
            #endregion

            #region 表单版本
            List<string> cookies = new List<string>();
            await GetCookieKey(fcpFormIds, cookies);
            foreach (var item in cookies)
            {
                t_form_version d = new t_form_version();
                d.org_id = model.OrgId;
                d.create_time = DateTime.Now;
                this.SetEntityId(d);
                d.remove_cookie_key = item;
                DoGetSqlByEntity(model.AccessType, d, rets, model.DestOrgId, model.SqlType);
            }
            #endregion

            return rets;

        }

        private async Task GetCookieKey(List<string> formIds,
            List<string> cookies)
        {
            var forms = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_form>(formIds);
            foreach (var form in forms)
            {
                cookies.Add(string.Format("form_config_form_{0}_{1}", form.code, form.org_id));
                cookies.Add(string.Format("form_config_custom_{0}_{1}", form.code, form.org_id));
                cookies.Add(string.Format("form_config_edit_{0}_{1}", form.code, form.org_id));
                cookies.Add(string.Format("form_config_tree_{0}_{1}", form.code, form.org_id));
                cookies.Add(string.Format("form_config_search_{0}_{1}", form.code, form.org_id));
                cookies.Add(string.Format("form_config_chart_{0}_{1}", form.code, form.org_id));
                cookies.Add(string.Format("form_config_table_{0}_{1}", form.code, form.org_id));
            }
        }

        private async Task GetSqlByFcpBaseAsync<T>(FCPSqlRequest model, List<string> fcpFormIds,
            List<string> sqlLists, Action<T> action)
            where T : t_fcpBase, new()
        {
            Expression<Func<T, bool>> expression = t => t.org_id == model.OrgId;
            if (!model.IsInitOrg && model.Time != null)
                expression = expression.And(t => t.modify_time > model.Time);
            if (!model.IsInitOrg && model.FormIds != null && model.FormIds.Any())
                expression = expression.And(t => model.FormIds.Contains(t.fcp_form_id));

            var entities = await this.fcpRepository.CommonRepository.GetEntitiesAsync<T>(expression);
            entities.ForEach(t =>
            {
                DoGetSqlByEntity(model.AccessType, t, sqlLists, model.DestOrgId, model.SqlType);
                if (string.IsNullOrEmpty(t.fcp_form_id) && !fcpFormIds.Contains(t.fcp_form_id))
                    fcpFormIds.Add(t.fcp_form_id);
                if (action != null)
                    action(t);
            });
        }
        private async Task GetSqlByFcpTreeBaseAsync<T>(FCPSqlRequest model, List<string> fcpFormIds,
           List<string> sqlLists, Action<T> action)
           where T : t_fcpTreeBase, new()
        {
            Expression<Func<T, bool>> expression = t => t.org_id == model.OrgId;
            if (!model.IsInitOrg && model.Time != null)
                expression = expression.And(t => t.modify_time > model.Time);
            if (!model.IsInitOrg && model.FormIds != null && model.FormIds.Any())
                expression = expression.And(t => model.FormIds.Contains(t.fcp_form_id));

            var entities = await this.fcpRepository.CommonRepository.GetEntitiesAsync<T>(expression);
            entities.ForEach(t =>
            {
                DoGetSqlByEntity(model.AccessType, t, sqlLists, model.DestOrgId, model.SqlType);
                if (string.IsNullOrEmpty(t.fcp_form_id) && !fcpFormIds.Contains(t.fcp_form_id))
                    fcpFormIds.Add(t.fcp_form_id);
                if (action != null)
                    action(t);
            });
        }

        private void DoGetSqlByEntity(DataBaseTypeEnum dataBaseType, object obj,
            List<string> result, string dstOrgId, int sqlType)
        {
            LibSysUtils.GetSqlByEntity(dataBaseType, obj, result, dstOrgId, sqlType);
        }



        public async Task<List<FCPFormAuth>> GetAllAuthFormByPlatformAsync(string orgId, int platformType,string lang)
        {
            List<FCPFormAuth> rets = new List<FCPFormAuth>();
            var forms = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_form>(t => t.org_id == orgId && t.platform_type == platformType); 
            //await EntityToWebModelUtls.GetFormLabelsAsync(forms, lang, this.fcpRepository.CommonRepository);

            var formIds = forms.Select(t => t.id).ToList();

            var customBtns = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_custom_btn>(t => formIds.Contains(t.fcp_form_id) && t.is_need_auth);
            var tableBtns = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_table_btn>(t => formIds.Contains(t.fcp_form_id) && t.is_need_auth);
            var treeBtns = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_tree_btn>(t => formIds.Contains(t.fcp_form_id) && t.is_need_auth);
            var editBtns = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_edit_btn>(t => formIds.Contains(t.fcp_form_id) && t.is_need_auth);
            await EntityToWebModelUtls.GetCustomBtnLabelsAsync(customBtns, lang, this.fcpRepository.CommonRepository);
            await EntityToWebModelUtls.GetTableBtnLabelsAsync(tableBtns, lang, this.fcpRepository.CommonRepository);
            await EntityToWebModelUtls.GetTreeBtnLabelsAsync(treeBtns, lang, this.fcpRepository.CommonRepository);
            await EntityToWebModelUtls.GetEditBtnLabelsAsync(editBtns, lang, this.fcpRepository.CommonRepository);

            var tableFields = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_table_field>(t => formIds.Contains(t.fcp_form_id) && t.is_need_auth);
            var editFields = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_edit_field>(t => formIds.Contains(t.fcp_form_id) && t.is_need_auth);

            await EntityToWebModelUtls.GetTableFieldLabelsAsync(tableFields, lang, this.fcpRepository.CommonRepository);
            await EntityToWebModelUtls.GetEditFieldLabelsAsync(editFields, lang, this.fcpRepository.CommonRepository);

            var formtableBtns = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_table_btn>(t => formIds.Contains(t.fcp_form_id) && t.form_code != null);


            forms.ForEach(t =>
            {
                var s = new FCPFormAuth()
                { 
                    FormCode = t.code,
                    FormId = t.id,
                    FormName = t.name,
                };
                customBtns.Where(t1 => t1.fcp_form_id == t.id).ForEach(t1 =>
                {
                    s.Btns.Add(new FCPFormAuthBtn() { BtnId = t1.id, BtnLabel = t1.vir_btn_label });
                });
                tableBtns.Where(t1 => t1.fcp_form_id == t.id).ForEach(t1 =>
                {
                    s.Btns.Add(new FCPFormAuthBtn() { BtnId = t1.id, BtnLabel = t1.vir_btn_label });
                });
                treeBtns.Where(t1 => t1.fcp_form_id == t.id).ForEach(t1 =>
                {
                    s.Btns.Add(new FCPFormAuthBtn() { BtnId = t1.id, BtnLabel = t1.vir_btn_label });
                });
                editBtns.Where(t1 => t1.fcp_form_id == t.id).ForEach(t1 =>
                {
                    s.Btns.Add(new FCPFormAuthBtn() { BtnId = t1.id, BtnLabel = t1.vir_btn_label });
                });

                tableFields.Where(t1 => t1.fcp_form_id == t.id).ForEach(t1 =>
                {
                    s.Fields.Add(new FCPFormAuthField() { FieldId = t1.id, FieldLabel = t1.vir_field_label });
                });
                editFields.Where(t1 => t1.fcp_form_id == t.id).ForEach(t1 =>
                {
                    s.Fields.Add(new FCPFormAuthField() { FieldId = t1.id, FieldLabel = t1.vir_field_label });
                });

                formtableBtns.Where(t1 => t1.fcp_form_id == t.id).ForEach(t1 =>
                {
                    var pp = forms.FirstOrDefault(t2 => t2.code == t1.form_code);
                    if (pp != null && !s.BtnFormIds.Contains(pp.id))
                        s.BtnFormIds.Add(pp.id);
                });

                rets.Add(s);
            });
            return rets;
        }



        public async Task<List<string>> GetFormLastVersionAsync(string orgId, DateTime? lastTime)
        {
            if (lastTime != null)
            {
                var s = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_form_version>(t => t.org_id == orgId && t.create_time >= lastTime.Value);
                if (s.Any())
                    return s.Select(t => t.remove_cookie_key).ToList();
            }
            return null;
        }


        public async Task<List<FCPForm>> GetAllFormByIdsAsync(List<string> formIds,string lang)
        {
            var forms = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_form>(formIds);
           // await EntityToWebModelUtls.GetFormLabelsAsync(forms, lang, this.fcpRepository.CommonRepository);
            return await GetFCPFormModelsAsync(forms);
        }


        private async Task<List<FCPForm>> GetFCPFormModelsAsync(List<t_form> forms)
        {
            List<FCPForm> rets = new List<FCPForm>();
            var customformIds = forms.Where(t => t.form_type == 0 || t.form_type == 5).Select(t => t.id).ToList();
            List<t_custom> customs = null;
            if (customformIds.Any())
                customs = this.fcpRepository.CommonRepository.GetEntities<t_custom>(t => customformIds.Contains(t.fcp_form_id));

            List<t_custom_btn> customBtns = null;
            if (customformIds.Any())
            {
                customBtns = this.fcpRepository.CommonRepository.GetEntities<t_custom_btn>(t => customformIds.Contains(t.fcp_form_id));
                await EntityToWebModelUtls.GetCustomBtnLabelsAsync(customBtns, lang, this.fcpRepository.CommonRepository);
            }

            forms.ForEach(t =>
            {
                var cu = customs != null ? customs.FirstOrDefault(t1 => t1.fcp_form_id == t.id) : null;
                var fff = new FCPForm()
                {
                    Code = t.code,
                    FormType = t.form_type,
                    Id = t.id,
                    ModuleType = t.module_type,
                    Name = t.name,
                    PlatformType = t.module_type,
                    FormPath = cu?.custom_info,
                };

                if (cu != null)
                {
                    customBtns?.Where(t => t.custom_id == cu.id).ForEach(t3 =>
                    {
                        fff.CustomBtns.Add(new FCPFormCustomBtn()
                        {
                            BtnCode = t3.code,
                            BtnId = t3.id,
                            BtnLabel = t3.vir_btn_label,
                            IsAuth = t3.is_need_auth,
                            ServiceCode = t3.service_code,
                            Api = t3.api,
                            IsVisible = t3.is_visible,
                            Num = t3.num,
                            BtnIcon = t3.btn_icon,
                            BtnCss = t3.btn_css,
                        });
                    });
                }

                rets.Add(fff);
            });
            return rets;
        }


        private void DoAddLabelDetail(t_label baseLabel, List<t_label_detail> baseLabelDetails, List<t_label_detail> addBaseLabelDetails, List<t_label_detail> updateBaseLabelDetails, string label, string langg)
        {
            var detail = baseLabelDetails?.FirstOrDefault(t => t.label_id == baseLabel.id && t.lang == langg);
            if (detail == null)
            {
                if (string.IsNullOrEmpty(label))
                {
                    return;
                }

                detail = new t_label_detail() { label_id = baseLabel.id, lang = langg, org_id = baseLabel.org_id };
                this.SetEntityId(detail, detail.label_id);
                addBaseLabelDetails.Add(detail);
                baseLabelDetails.Add(detail);
            }
            else
            {
                updateBaseLabelDetails.Add(detail);
            }

            detail.label = label;
        }


        private async Task FillLangDataByBaseLabelAsync(List<m_label> list)
        {
            if (list == null)
            {
                return;
            }

            var baseLabelIds = list.Select(t => t.id).ToList();
            var baseLabelDetails = await this.fcpRepository.CommonRepository.GetEntitiesAsync<t_label_detail>(null, t => baseLabelIds.Contains(t.label_id));
            baseLabelDetails.ForEach(t =>
            {
                var le = list.FirstOrDefault(t2 => t2.id == t.label_id);
                if (le == null)
                {
                    return;
                }

                var l = string.IsNullOrEmpty(t.lang) ? lang : t.lang;

                if (l?.Trim().ToLower() == "cn")
                {
                    le.label_label_cn = t.label;
                }
                else if (l?.Trim().ToLower() == "en")
                {
                    le.label_label_en = t.label;
                }
                else if (l?.Trim().ToLower() == "th")
                {
                    le.label_label_th = t.label;
                }
            });
        }
    }
}
